package org.ucn.dmaa0914.temadesign.group2.modelLayer;

import org.ucn.dmaa0914.temadesign.group2.tuiLayer.Application;

import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;

/**
 * The Loan class description
 * 
 * @author Christian "Chriss" Mortensen
 * @version 05-11-2014
 */
public class Loan
{    
    // Id counter for making unique id's
    private static int idCounter = 0;
    
    private int id;
    
    private Date borrowDateFrom;
    private Date borrowDateTo;
    private Person loaner;
    
    private HashSet<Copy> copySet;

    /**
     * Constructor for objects of class Person
     */
    public Loan(Date borrowDateFrom, Date borrowDateTo, Person loaner)
    {
        // initialise instance variables and assign a new id
        this.id = idCounter++;
        this.borrowDateFrom = borrowDateFrom;
        this.borrowDateTo = borrowDateTo;
        this.loaner = loaner;
        this.copySet = new HashSet<Copy>();
    }
    
    public String makeDescription()
    {
        String copyText = "";
        for(Copy c : copySet)
        {
            if( c.getCurrentLoan() == this )
            {
                copyText += "    " + c.toString() + "\n";
            }
            else if( c.getCurrentLoan() == null )
            {
                copyText += "    " + c.toString() + " (Returned)\n";
            }
            else
            {
                copyText += "    " + c.toString() + " (Returned and Lent To Someone Else)\n";
            }
        }
        
        return "ID: " + String.valueOf(getId()) + "\n" +
               "Borrower: " + getLoaner().toString() + "\n" +
               "Borrow Date: " + Application.instance.dateFormat.format(getBorrowDateFrom()) + "\n" +
               "Last Delivery Date: " + Application.instance.dateFormat.format(getBorrowDateTo()) + "\n" +
               "Copies: \n\n" + copyText;
    }
    
    public String toString()
    {
        return String.valueOf(id) + " @ " + loaner.getName() + " (" + String.valueOf(copySet.size()) + ")";
    }

    public int getId()
    {
        return id;
    }
    
    public Date getBorrowDateFrom()
    {
        return borrowDateFrom;
    }
    
    public Date getBorrowDateTo()
    {
        return borrowDateTo;
    }
    
    public Person getLoaner()
    {
        return loaner;
    }
    
    public void setId(int value)
    {
        this.id = value;
    }
    
    public void setBorrowDateFrom(Date value)
    {
        this.borrowDateFrom = value;
    }
    
    public void setBorrowDateTo(Date value)
    {
        this.borrowDateTo = value;
    }
    
    /**
     * addCopy adds a copy to this loan if possible. If the copy is not
     * currently in another loan, the copy's current loaner is set to this
     * loan, and the copy is added to the copySet. If the copy is already in
     * a loan, nothing is done.
     * 
     * @param copy The copy to add to this loan.
     * 
     * @return True if the copy was added successfully to this loan. False if
     * the copy is already in another loan.
     */
    public boolean addCopy(Copy copy)
    {
        if( copy.getCurrentLoan() != null )
        {
            return false; // Copy is already lent out.
        }
        
        copy.setCurrentLoan(this);
        copySet.add(copy);
        
        return true;
    }
    
    /**
     * @return True if this loan has expired. False if not.
     */
    public boolean isExpired()
    {
        return borrowDateTo.before(new Date());
    }
    
    /**
     * @return True if any of the copies has not been returned yet.
     * False if this loan is fully returned.
     */
    public boolean isActive()
    {
        Iterator<Copy> i = copySet.iterator();
        
        while(i.hasNext())
        {
            Copy copy = i.next();
            if( copy.getCurrentLoan() == this )
            {
                return true;
            }
        }
        
        return false;
    }
}
